package com.pajx.testopengles.views.three_d

import android.content.Context
import android.opengl.GLES20
import android.util.Log
import com.pajx.testopengles.util.GLCameraLightHelper
import com.pajx.testopengles.util.GLHelper
import com.pajx.testopengles.util.MatrixStack
import com.pajx.testopengles.word.Cons
import com.pajx.testopengles.word.RenderAble
import java.nio.FloatBuffer
import kotlin.math.cos
import kotlin.math.sin

/**
 *User: RandBII
 *Date: 2020/8/19
 *Description: 球体(镜面光)
 *
 * //TODO 模拟器跑不开（崩溃）真机可以
 *
 *
 * 球体坐标点 公式(此 sin,cos 是数学公式中的 a, b  是角度)
 *
 * x = R* cos（a）* sin（b）
 * y =R* sin(a)
 * z = R* cos(a) *cos(b)
 *
 */

class MirrorBallShape(context: Context) : RenderAble(context) {

    private val mR = 0.8f
    private val mContext = context
    private var mProgram = -1
    private var mPositionHandle = -1
    private var muRHandle = -1
    private var mMVPMatrixHandle = -1
    private var muAmbientHandle = -1  //  环境光句柄


    private var uMMatrixHandle = -1 // 变换矩阵
    private var uLightLocationHandle = -1 // 光源
    private var aNormalHandle = -1 // 顶点法向量
    private var mCameraHandle = -1// 相机 句柄

    private val shaderCode = GLHelper.loadShaderAsserts(mContext, "ball_vert_light_mirror.glsl")
    private val fragmentCode = GLHelper.loadShaderAsserts(mContext, "ball_frag_light_mirror.glsl")

    private var mVertexBuffer: FloatBuffer? = null

    private val VERTEX_STRIDE = Cons.DIMENSION_3 * 4

    private var vertexes: FloatArray? = null


    init {

        vertexes = generatePositionVertexes()

        mVertexBuffer = GLHelper.getFloatBuffer(vertexes!!)

        val shaderId = GLHelper.loadShader(GLES20.GL_VERTEX_SHADER, shaderCode)
        val fragmentId = GLHelper.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentCode)

        mProgram = GLES20.glCreateProgram()
        GLES20.glAttachShader(mProgram, shaderId)
        GLES20.glAttachShader(mProgram, fragmentId)
        GLES20.glLinkProgram(mProgram)
        GLHelper.validateProgram(mProgram)

        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition")
        muRHandle = GLES20.glGetUniformLocation(mProgram, "uR")
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix")
        muAmbientHandle = GLES20.glGetUniformLocation(mProgram, "uAmbient")

        uMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix")
        aNormalHandle = GLES20.glGetAttribLocation(mProgram, "aNormal")
        uLightLocationHandle = GLES20.glGetUniformLocation(mProgram, "uLightLocation")
        mCameraHandle = GLES20.glGetUniformLocation(mProgram, "uCamera")


        Log.e(
            "-->",
            "ball--shaderId--:${shaderId}  fragmentId--:${fragmentId}  mProgram --: ${mProgram}"
        )


    }

    private fun generatePositionVertexes(): FloatArray? {
        // 类似下图计算点位
        //-------/-2----/-3-
//              /     /
        // ----/-1---/ 0---
        ///
        val angle = 10 //将球进行分割的角度
        val R = 0.8f
        val tempArray: MutableList<Float> = mutableListOf()

        for (vAngle in -90 until 90 step angle) { //纵向分割

            for (hAngle in 0 until 360 step angle) { // 横向分割

                val x0 =
                    R * cos(a2r(vAngle)) * sin(a2r(hAngle))
                val y0 = R * sin(a2r(vAngle))
                val z0 =
                    R * cos(a2r(vAngle)) * cos(a2r(hAngle))


                val x1 =
                    R * cos(a2r(vAngle)) * sin(a2r(hAngle + angle))
                val y1 = R * sin(a2r(vAngle))
                val z1 =
                    R * cos(a2r(vAngle)) * cos(a2r(hAngle + angle))

                val x2 =
                    R * cos(a2r(vAngle + angle)) * sin(a2r(hAngle))
                val y2 = R * sin(a2r(vAngle + angle))
                val z2 =
                    R * cos(a2r(vAngle + angle)) * cos(a2r(hAngle))

                val x3 =
                    R * cos(a2r(vAngle + angle)) * sin(a2r(hAngle))
                val y3 = R * sin(a2r(vAngle + angle))
                val z3 =
                    R * cos(a2r(vAngle + angle)) * cos(a2r(hAngle))


                tempArray.add(x1.toFloat())
                tempArray.add(y1.toFloat())
                tempArray.add(z1.toFloat())

                tempArray.add(x3.toFloat())
                tempArray.add(y3.toFloat())
                tempArray.add(z3.toFloat())

                tempArray.add(x0.toFloat())
                tempArray.add(y0.toFloat())
                tempArray.add(z0.toFloat())


                // 第二个三角形
                tempArray.add(x1.toFloat())
                tempArray.add(y1.toFloat())
                tempArray.add(z1.toFloat())

                tempArray.add(x2.toFloat())
                tempArray.add(y2.toFloat())
                tempArray.add(z2.toFloat())

                tempArray.add(x3.toFloat())
                tempArray.add(y3.toFloat())
                tempArray.add(z3.toFloat())

            }

        }

        return tempArray.toFloatArray()

    }

    /**
     * angle to   radians
     * 角度转换为弧度
     */
    private fun a2r(vAngle: Int) = Math.toRadians(vAngle.toDouble())


    override fun draw(matrix: FloatArray) {

        GLES20.glUseProgram(mProgram)
        GLES20.glEnableVertexAttribArray(mPositionHandle)
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, matrix, 0)
        GLES20.glUniform1f(muRHandle, mR * Cons.UNIT_SIZE)
        GLES20.glUniform4f(muAmbientHandle, 1f, 1f, 1f, 1f)
        GLCameraLightHelper.changeLightLocation(1f, 1f, -1f)
        // 变换矩阵
        GLES20.glUniformMatrix4fv(uMMatrixHandle, 1, false, MatrixStack.mOptionMatrix, 0)
        GLES20.glUniform3fv(uLightLocationHandle, 1, GLCameraLightHelper.lightPositionFB)

        //将摄像机位置传入着色器程序
        GLES20.glUniform3fv(mCameraHandle, 1, GLCameraLightHelper.cameraPositionFB);

        // 顶点法向量
        GLES20.glVertexAttribPointer(
            aNormalHandle,
            Cons.DIMENSION_3,
            GLES20.GL_FLOAT,
            false,
            VERTEX_STRIDE,
            mVertexBuffer
        )


        // 顶点数据
        GLES20.glVertexAttribPointer(
            mPositionHandle,
            Cons.DIMENSION_3,
            GLES20.GL_FLOAT,
            false,
            VERTEX_STRIDE,
            mVertexBuffer
        )

        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexes!!.size / Cons.DIMENSION_3)
        GLES20.glDisableVertexAttribArray(mPositionHandle)
    }

}